home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************/
- /* */
- /* CDT - a small shell utility to deal with a CD-ROM (based on SCSIutil ;) */
- /* - written by Gunther Nikl in 11/1995 */
- /* - can *only* be compiled with gcc ... */
- /* */
- /***************************************************************************/
-
- /***************************************************************************/
- /* */
- /* includes */
- /* */
- /***************************************************************************/
-
- #include <exec/types.h>
-
- #ifndef CONST
- #define CONST const
- #endif
- #ifndef INLINE
- #define INLINE inline
- #endif
-
- #include <exec/io.h>
- #include <exec/memory.h>
- #include <dos/dosextens.h>
- #include <dos/filehandler.h>
- #include <devices/scsidisk.h>
-
- /*
- ** structure definitions now!
- */
-
- struct PortIO {
- struct IOStdReq req;
- struct MsgPort port;
- };
-
- /*
- ** sizeof(struct Globals) _MUST_ be a multiple of 4 !
- */
-
- struct Globals {
-
- /*** library stuff ***/
-
- struct ExecBase *SysBase;
- struct DosLibrary *DosBase;
-
- /*** io stuff ***/
-
- STRPTR ScsiName;
- ULONG ScsiUnit;
- struct PortIO *ScsiIO;
- struct SCSICmd ScsiCmd;
- UBYTE Pad[2],
- *ScsiData,
- *SenseBuf,
- *TocBuf,
- Command[12];
- LONG HaveCmd,
- Arg1,Arg2;
- };
-
- /*
- ** ptr to the `global' data space (will be on the stack :-)
- */
-
- register struct Globals *gb asm("a4");
-
- /*
- ** redirect global library bases to the `global' data space
- */
-
- #define BASE_NAME gb->SysBase
- #include <proto/exec.h>
- #undef BASE_NAME
-
- #define BASE_NAME gb->DosBase
- #include <proto/dos.h>
- #undef BASE_NAME
-
- /*
- ** strcpy() && strlen()
- */
-
- #include <string.h>
-
- /*
- ** SCSI-2 stuff (taken from the ANSI draft, ct 11/1993 and SCSIutil)
- */
-
- #include "cdt_scsi.h"
-
- /***************************************************************************/
- /* */
- /* prototypes */
- /* */
- /***************************************************************************/
-
- struct PortIO *OpenSCSI(STRPTR,ULONG);
- LONG GetBuffers();
- LONG GetArguments();
- VOID Main();
- LONG StartAudioPlay(LONG,LONG);
- LONG PauseResumePlay(LONG);
- VOID ShowInfo();
- LONG DoScsiCmd(UBYTE *,LONG,UBYTE *,LONG,LONG);
- VOID FreeBuffers();
- VOID CloseSCSI(struct PortIO *);
- VOID PrintF(STRPTR,...);
-
- /***************************************************************************/
- /* */
- /* ReadArgs() peculiarities + other defines */
- /* */
- /***************************************************************************/
-
- enum {
- DEVICEARG=0,UNITARG,STARTTRACKARG,STARTINDEXARG,LASTTRACKARG,LASTINDEXARG,
- LOADARG,EJECTARG,LOCKARG,UNLOCKARG,PLAYARG,STOPARG,PAUSEARG,RESUMEARG,
- INFOARG,MAXARG
- };
-
- #define TEMPLATE "D=DEVICE,U=UNIT/K/N,STARTTRACK/N,STARTINDEX/N,LASTTRACK/N," \
- "LASTINDEX/N,LOAD/S,EJECT/S,LOCK/S,UNLOCK/S,PLAY/S,STOP/S," \
- "PAUSE/S,RESUME/S,INFO/S"
-
- #define DEFDEVICE "scsi.device"
- #define DEFUNIT 4
-
- #define NEWLIST(l) ((l)->lh_Head = (struct Node *)&(l)->lh_Tail, \
- /*(l)->lh_Tail = NULL,*/ \
- (l)->lh_TailPred = (struct Node *)&(l)->lh_Head)
-
- /***************************************************************************/
- /* */
- /* memory clear function (!!! caution: size _MUST_ be a multiple of 4!!!) */
- /* */
- /***************************************************************************/
-
- STATIC INLINE VOID MEMZEROL(VOID *mem,ULONG size)
- { ULONG *p;
- WORD s;
-
- for(p=(ULONG *)mem,s=(size/sizeof(ULONG))-1; s>=0; *p++=NULL,s--);
- }
-
- /***************************************************************************/
- /* */
- /* implementation */
- /* */
- /***************************************************************************/
-
- LONG Start()
- {
- struct Globals globals;
-
- MEMZEROL(&globals,sizeof(struct Globals)); gb = &globals;
-
- gb->SysBase = *(struct ExecBase **)4L;
-
- Main();
-
- return 0;
- }
-
- /***************************************************************************/
- /* */
- /* version string */
- /* */
- /***************************************************************************/
-
- CONST UBYTE verstag[]="$VER: CDT 1.0 (8.11.95) © 1995 by G.Nikl";
-
- /***************************************************************************/
- /* */
- /* open scsi device */
- /* */
- /***************************************************************************/
-
- struct PortIO *OpenSCSI(STRPTR DeviceName,ULONG DeviceUnit)
- {
- struct PortIO *portio;
-
- if ((portio=(struct PortIO *)AllocMem(sizeof(struct PortIO),MEMF_CLEAR|MEMF_PUBLIC)))
- {
- portio->port.mp_Node.ln_Type=NT_MSGPORT;
- if ((BYTE)(portio->port.mp_SigBit=AllocSignal(-1))>=0)
- {
- portio->port.mp_SigTask=FindTask(NULL);
- NEWLIST(&portio->port.mp_MsgList);
- portio->req.io_Message.mn_Node.ln_Type=NT_MESSAGE;
- portio->req.io_Message.mn_ReplyPort=&portio->port;
- if (!(OpenDevice(DeviceName,DeviceUnit,(struct IORequest *)&portio->req,0)))
- return portio;
- FreeSignal(portio->port.mp_SigBit);
- }
- FreeMem(portio,sizeof(struct PortIO)); portio=NULL;
- }
- return portio;
- }
-
- /***************************************************************************/
- /* */
- /* allocate all buffers */
- /* */
- /***************************************************************************/
-
- LONG GetBuffers()
- {
- LONG ret=0;
-
- if ((gb->ScsiData=AllocMem(DATALEN,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
- if ((gb->SenseBuf=AllocMem(SENSELEN,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
- if ((gb->TocBuf=AllocMem(TOCLEN,MEMF_CHIP|MEMF_PUBLIC)) != NULL)
- ret=1;
- return ret;
- }
-
- /***************************************************************************/
- /* */
- /* read arguments */
- /* */
- /***************************************************************************/
-
- LONG GetArguments()
- {
- struct FileSysStartupMsg *fssm;
- struct DosList *dol;
- struct RDArgs *rda;
- STRPTR name,p;
- ULONG unit;
- LONG args[MAXARG],size,tmp,value,i,*ptr,ret=0;
-
- MEMZEROL(&args[0],sizeof(args));
- if ((rda=ReadArgs(TEMPLATE,&args[0],NULL)) != NULL)
- {
- i=MAXARG-LOADARG; ptr=&args[LOADARG];
- do {} while(!(gb->HaveCmd=*ptr++) && --i);
-
- if (args[UNLOCKARG] || args[LOCKARG])
- {
- gb->Command[0] = SCSI_CMD_PAMR;
- gb->Command[4] = (args[LOCKARG] ? 1 : 0);
- }
-
- if (args[EJECTARG] || args[LOADARG])
- {
- gb->Command[0] = SCSI_CMD_SSU;
- gb->Command[4] = (args[LOADARG] ? 1 : 0) + 2;
- }
-
- if (args[PAUSEARG] || args[RESUMEARG])
- {
- gb->Command[0] = SCSI_CMD_RQS;
- gb->Command[4] = SENSELEN;
- ((UBYTE *)&gb->Arg1)[3] = (args[RESUMEARG] ? 1 : 0);
- }
-
- if (args[STOPARG])
- {
- gb->Command[0] = SCSI_CMD_SSU;
- gb->Command[4] = 0;
- }
-
- if (!args[INFOARG] && args[PLAYARG])
- {
- gb->Command[0] = SCSI_CMD_PLAYAUDIOTRACKINDEX;
-
- value = 1;
- if (args[STARTTRACKARG])
- {
- tmp = *(LONG *)args[STARTTRACKARG];
- if (tmp > 0 && tmp < 100)
- value = tmp;
- }
- gb->Command[4] = value; gb->Arg1 = value;
-
- value = 0;
- if (args[STARTINDEXARG])
- {
- tmp = *(LONG *)args[STARTINDEXARG];
- if (tmp >= 0 && tmp < 100)
- value = tmp;
- }
- gb->Command[5] = value;
-
- value = 99;
- if (args[LASTTRACKARG])
- {
- tmp = *(LONG *)args[LASTTRACKARG];
- if (tmp > 0 && tmp < 100 && tmp > gb->Arg1)
- value = tmp;
- }
- gb->Command[7] = value; gb->Arg2 = value;
-
- value = 0;
- if (args[LASTINDEXARG])
- {
- tmp = *(LONG *)args[LASTINDEXARG];
- if (tmp >= 0 && tmp < 100)
- value = tmp;
- }
- gb->Command[8] = value;
- }
-
- if (args[INFOARG])
- {
- gb->Command[0] = SCSI_CMD_INQ;
- gb->Command[4] = DATALEN;
- }
-
- unit = DEFUNIT;
- if (args[UNITARG])
- unit = *(ULONG *)args[UNITARG];
- gb->ScsiUnit=unit;
-
- name = DEFDEVICE;
- if (args[DEVICEARG])
- name = (STRPTR)args[DEVICEARG];
- if ((size=((tmp=strlen(name))+1+3)&~3) < 256)
- size = 256;
- if ((gb->ScsiName=AllocVec(size,MEMF_ANY)) != NULL)
- {
- name=strcpy(gb->ScsiName,name);
- if (name[tmp-1] == ':')
- {
- name[tmp-1] = '\0';
- dol=FindDosEntry(LockDosList(LDF_READ|LDF_DEVICES),name,LDF_DEVICES);
- name[0] = '\0';
- if (dol != NULL)
- {
- fssm=(struct FileSysStartupMsg *)BADDR(dol->dol_misc.dol_handler.dol_Startup);
- if (TypeOfMem(fssm))
- {
- if (TypeOfMem((p=BADDR(fssm->fssm_Device))))
- {
- strcpy(name,1+p); gb->ScsiUnit = fssm->fssm_Unit;
- }
- }
- }
- UnLockDosList(LDF_READ|LDF_DEVICES);
- if (name[0] == '\0')
- strcpy(name,DEFDEVICE);
- }
- ret = 1;
- }
- FreeArgs(rda);
- }
- else
- PrintFault(IoErr(),NULL);
- return ret;
- }
-
- /***************************************************************************/
- /* */
- /* main function */
- /* */
- /***************************************************************************/
-
- #define CmdLen (gb->Command[0] != SCSI_CMD_PLAYAUDIOTRACKINDEX ? 6 : 10)
-
- VOID Main()
- {
- LONG err;
-
- if ((gb->DosBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) != NULL)
- {
- if (GetArguments())
- {
- if (GetBuffers())
- {
- if ((gb->ScsiIO=OpenSCSI(gb->ScsiName,gb->ScsiUnit)) != NULL)
- {
- if (gb->HaveCmd)
- {
- err = DoScsiCmd(gb->ScsiData,DATALEN,&gb->Command[0],CmdLen,(SCSIF_READ|SCSIF_AUTOSENSE));
-
- if (err != 0 && gb->Command[0] == SCSI_CMD_PLAYAUDIOTRACKINDEX)
- err = StartAudioPlay(gb->Arg1,gb->Arg2);
- else
- switch (gb->Command[0])
- {
- case SCSI_CMD_RQS:
- err = PauseResumePlay(gb->Arg1);
- break;
- case SCSI_CMD_INQ:
- ShowInfo();
- default:
- break;
- }
-
- if (err != 0 && gb->ScsiCmd.scsi_SenseActual >= OFFS_KEY)
- PrintF("direct command failed! (Sense: 0x%02lx, Code: 0x%02lx, Qualifier: 0x%02lx)\n",
- (LONG)gb->SenseBuf[OFFS_KEY]&0xf,(LONG)gb->SenseBuf[OFFS_CODE],(LONG)gb->SenseBuf[OFFS_QUAL]);
- }
- CloseSCSI(gb->ScsiIO);
- }
- else
- PrintF("couldn't open `%s' unit `%ld'\n",gb->ScsiName,gb->ScsiUnit);
- }
- FreeBuffers();
- FreeVec(gb->ScsiName);
- }
- CloseLibrary(&(gb->DosBase->dl_lib));
- }
- }
-
- /***************************************************************************/
- /* */
- /* PlayAudioTrackIndex (0x48) failed so try it with another play command */
- /* */
- /***************************************************************************/
-
- LONG StartAudioPlay(LONG First,LONG Last)
- {
- UBYTE *data,*toc;
- LONG err,tmp,index;
-
- data=&gb->Command[0];
-
- *(LONG *)&data[0] = 0; *(LONG *)&data[4] = 0; *(LONG *)&data[8] = 0;
-
- data[0] = SCSI_CMD_READTOC;
- data[7] = ((TOCLEN >> 8) & 0xFF);
- data[8] = ((TOCLEN >> 0) & 0xFF);
-
- if ((err=DoScsiCmd(gb->TocBuf,TOCLEN,data,10,(SCSIF_READ|SCSIF_AUTOSENSE))) == 0)
- {
- toc=gb->TocBuf;
-
- if ((tmp=toc[3]) < Last)
- if ((Last=tmp) < First)
- First = 1;
-
- data[0] = SCSI_CMD_PLAYAUDIO12;
-
- index = 8*First;
- First = 1 + ((toc[index] << 24) | (toc[index+1] << 16) | (toc[index+2] << 8) | (toc[index+3]));
- data[2] = ((First >> 24) & 0xFF);
- data[3] = ((First >> 16) & 0xFF);
- data[4] = ((First >> 8) & 0xFF);
- data[5] = ((First >> 0) & 0xFF);
-
- index = 8*Last+8;
- Last = -2 + ((toc[index] << 24) | (toc[index+1] << 16) | (toc[index+2] << 8) | (toc[index+3]));
- Last -= First;
- data[6] = ((Last >> 24) & 0xFF);
- data[7] = ((Last >> 16) & 0xFF);
- data[8] = ((Last >> 8) & 0xFF);
- data[9] = ((Last >> 0) & 0xFF);
-
- err = DoScsiCmd(gb->ScsiData,DATALEN,data,12,(SCSIF_READ|SCSIF_AUTOSENSE));
- }
- return err;
- }
-
- /***************************************************************************/
- /* */
- /* Pause / Resume audio play (REQUEST SENSE was done before) */
- /* */
- /***************************************************************************/
-
- LONG PauseResumePlay(LONG What)
- {
- UBYTE *data = gb->ScsiData;
- LONG audio,err = 0;
-
- if ((BYTE)(data[OFFS_KEY]&0xf) == 0)
- {
- audio = data[OFFS_QUAL];
-
- if ((audio == 0x11 && What == 0) || (audio == 0x12 && What == 1))
- {
- data=&gb->Command[0];
-
- *(LONG *)&data[0] = 0; *(LONG *)&data[4] = 0; *(LONG *)&data[8] = 0;
-
- data[0] = SCSI_CMD_PAUSERESUME;
- data[8] = What;
-
- err = DoScsiCmd(gb->ScsiData,DATALEN,data,10,(SCSIF_READ|SCSIF_AUTOSENSE));
- }
- }
- return err;
- }
-
- /***************************************************************************/
- /* */
- /* display inquiry information */
- /* */
- /***************************************************************************/
-
- CONST UBYTE *CONST DeviceType[] = {
- "Direct-access device (e.g., magnetic disk)",
- "Sequential-access device (e.g., magnetic tape)",
- "Printer device",
- "Processor device",
- "Write-once device (e.g., some optical disks)",
- "CD-ROM device",
- "Scanner device",
- "Optical memory device (e.g., some optical disks)",
- "Medium Changer device (e.g., jukeboxes)",
- "Communications device",
- "Defined by ASC IT8 (Graphic Arts Pre-Press Devices)",
- "Defined by ASC IT8 (Graphic Arts Pre-Press Devices)",
- "Reserved, unknown or no device type"
- };
-
- CONST UBYTE *CONST AnsiVersion[] = {
- "The device might or might not comply to an ANSI-approved standard.",
- "The device complies to ANSI X3.131-1986 (SCSI-1).",
- "The device complies to ANSI X?.???-???? (SCSI-2).",
- "Reserved",
- };
-
- CONST UBYTE *CONST ResponseFormat[] = {
- "SCSI-1",
- "CCS",
- "SCSI-2",
- "Reserved",
- };
-
- CONST UBYTE *CONST DataTransfer[] = {
- "8-bit only",
- "16-bit",
- "32-bit",
- "16 and 32-bit"
- };
-
- VOID ShowInfo()
- {
- UBYTE *data=gb->ScsiData;
- STRPTR p1,p2;
- ULONG index;
-
- if ((index=data[0]&0x1f) > 0x0b)
- index = 0x0c;
- PrintF("Device type : %s\n",DeviceType[index]);
-
- if ((index=data[2]&0x07) > 0x02)
- index = 0x03;
- PrintF("ANSI-approved version: %s\n",AnsiVersion[index]);
-
- if ((index=data[3]&0x0f) > 0x02)
- index = 0x03;
- PrintF("Response data format : %s\n",ResponseFormat[index]);
-
- PrintF("Vendor : %.8s\n",&data[8]);
- PrintF("Product : %.16s\n",&data[16]);
- PrintF("Revision : %.4s\n",&data[32]);
-
- index = (data[7]&0x60)>>5;
- PrintF("Transfer : %s\n",DataTransfer[index]);
-
- p1 = "not removable"; p2 = p1 + 4;
- PrintF("Medium : %s\n",(data[1]&0x80 ? p2 : p1));
-
- p1 = "not supported"; p2 = p1 + 4;
- PrintF("Relative addressing : %s\n",(data[7]&0x80 ? p2 : p1));
- PrintF("Synchronous transfer : %s\n",(data[7]&0x10 ? p2 : p1));
- PrintF("Linked command : %s\n",(data[7]&0x08 ? p2 : p1));
- PrintF("Command queuing : %s\n",(data[7]&0x02 ? p2 : p1));
- PrintF("Soft reset : %s\n",(data[7]&0x01 ? p2 : p1));
- }
-
- /***************************************************************************/
- /* */
- /* issue a scsi command */
- /* */
- /***************************************************************************/
-
- LONG DoScsiCmd(UBYTE *data,LONG datasize,UBYTE *cmd,LONG cmdsize,LONG flags)
- {
- struct PortIO *portio;
- struct SCSICmd *scmd;
-
- portio = gb->ScsiIO;
- portio->req.io_Command = HD_SCSICMD;
- scmd = &gb->ScsiCmd;
- portio->req.io_Data = (APTR)scmd;
- portio->req.io_Length = sizeof(struct SCSICmd);
-
- scmd->scsi_Data = (APTR)data;
- scmd->scsi_Length = datasize;
- scmd->scsi_SenseActual = 0;
- scmd->scsi_SenseData = gb->SenseBuf;
- scmd->scsi_SenseLength = SENSELEN;
- scmd->scsi_Command = cmd;
- scmd->scsi_CmdLength = cmdsize;
- scmd->scsi_Flags = flags;
-
- DoIO((struct IORequest *)&portio->req);
-
- return portio->req.io_Error;
- }
-
- /***************************************************************************/
- /* */
- /* free all buffers */
- /* */
- /***************************************************************************/
-
- VOID FreeBuffers()
- {
- APTR buf;
-
- if ((buf=gb->TocBuf) != NULL)
- FreeMem(buf,TOCLEN);
- if ((buf=gb->SenseBuf) != NULL)
- FreeMem(buf,SENSELEN);
- if ((buf=gb->ScsiData) != NULL)
- FreeMem(buf,DATALEN);
- }
-
- /***************************************************************************/
- /* */
- /* close scsi device */
- /* */
- /***************************************************************************/
-
- VOID CloseSCSI(struct PortIO *portio)
- {
- CloseDevice((struct IORequest *)&portio->req);
- FreeSignal(portio->port.mp_SigBit);
- FreeMem(portio,sizeof(struct PortIO));
- }
-
- /***************************************************************************/
- /* */
- /* vararg printf() with VPrintf() from the dos.library (can't use Printf())*/
- /* */
- /***************************************************************************/
-
- VOID PrintF(STRPTR format,...)
- {
- VPrintf(format,(APTR)(&format+1));
- }
-
- /***************************************************************************/
- /* */
- /* The End */
- /* */
- /***************************************************************************/
-